package uk.ac.ebi.pride.peptidome;

import uk.ac.ebi.pride.jaxb.model.*;
import uk.ac.ebi.pride.peptidome.model.*;
import uk.ac.ebi.pride.tools.mgf_parser.MgfFile;
import uk.ac.ebi.pride.tools.mgf_parser.model.Ms2Query;

import java.io.File;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: rwang
 * Date: 20/05/11
 * Time: 10:47
 */
public class PeptidomeToPrideInterpreter {
    private final PeptidomeReader peptidomeReader;
    private final String sampleAcc;

    private final Map<String, ModificationItem> unimodPTMs;


    public PeptidomeToPrideInterpreter(PeptidomeReader peptidomeReader, String sampleAcc,
                                       Map<String, ModificationItem> unimodPTMs) {
        this.sampleAcc = sampleAcc;

        // create a peptidome peptidomeReader
        this.peptidomeReader = peptidomeReader;

        // get unimod ptms
        this.unimodPTMs = new HashMap<String, ModificationItem>();
        if (unimodPTMs != null) {
            this.unimodPTMs.putAll(unimodPTMs);
        }
    }

    public String getSampleAccession() {
        return sampleAcc;
    }

    public String getExperimentTitle() {
        return peptidomeReader.getSampleTitle(sampleAcc);
    }

    public List<Reference> getReferences() {
        List<Reference> refs = new ArrayList<Reference>();
        List<String> pubmedIds = peptidomeReader.getPubMedIds();
        if (pubmedIds != null) {
            for (String pubmedId : pubmedIds) {
                Reference ref = new Reference();
                ref.setRefLine(PubMedFetcher.fetch(pubmedId));
                Param param = new Param();
                List<CvParam> cvParams = param.getCvParam();
                CvParam cvParam = new CvParam();
                cvParam.setCvLabel("PubMed");
                cvParam.setAccession(pubmedId);
                cvParam.setName(pubmedId);
                cvParam.setValue(pubmedId);
                cvParams.add(cvParam);
                ref.setAdditional(param);
                refs.add(ref);
            }
        }
        return refs;
    }

    public Protocol getProtocol() {
        Protocol protocol = new Protocol();
        protocol.setProtocolName("protocol 1");
        MSSample.Preparation preparation = peptidomeReader.getSamplePreparation(sampleAcc);
        ProtocolSteps steps = new ProtocolSteps();
        protocol.setProtocolSteps(steps);
        List<Param> params = steps.getStepDescription();

        // 1. growth
        List<String> growth = preparation.getGrowth();
        if (growth != null) {
            Param param = new Param();
            List<UserParam> userParam = param.getUserParam();
            for (String g : growth) {
                UserParam up = new UserParam();
                up.setName("Growth");
                up.setValue(g);
                userParam.add(up);
            }
            params.add(param);
        }

        // 2. treatment
        List<String> treatment = preparation.getTreatment();
        if (treatment != null) {
            Param param = new Param();
            List<UserParam> userParam = param.getUserParam();
            for (String t : treatment) {
                UserParam tr = new UserParam();
                tr.setName("Treatment");
                tr.setValue(t);
                userParam.add(tr);
            }
            params.add(param);
        }

        // 3. extract
        List<String> extract = preparation.getExtract();
        if (extract != null) {
            Param param = new Param();
            List<UserParam> userParam = param.getUserParam();
            for (String e : extract) {
                UserParam ex = new UserParam();
                ex.setName("Growth");
                ex.setValue(e);
                userParam.add(ex);
            }
            params.add(param);
        }

        // 4. digestion
        List<String> digestion = preparation.getDigestion();
        if (digestion != null) {
            Param param = new Param();
            List<UserParam> userParam = param.getUserParam();
            for (String d : digestion) {
                UserParam di = new UserParam();
                di.setName("Digestion");
                di.setValue(d);
                userParam.add(di);
            }
            params.add(param);
        }

        // 5. separation
        List<String> separation = preparation.getSeparation();
        if (separation != null) {
            Param param = new Param();
            List<UserParam> userParam = param.getUserParam();
            for (String s : separation) {
                UserParam se = new UserParam();
                se.setName("Separation");
                se.setValue(s);
                userParam.add(se);
            }
            params.add(param);
        }

        return protocol;
    }

    public List<CvLookup> getCvLookup() {
        List<CvLookup> cvLookups = new ArrayList<CvLookup>();

        cvLookups.add(buildCvLookup("MS", "PSI Mass Spectrometry Ontology", "1.2", "http://psidev.cvs.sourceforge.net/viewvc/*checkout*/psidev/psi/psi-ms/mzML/controlledVocabulary/psi-ms.obo"));
        cvLookups.add(buildCvLookup("PRIDE", "PRIDE Controlled Vocabulary", "1.101", "http://ebi-pride.googlecode.com/svn/trunk/pride-core/schema/pride_cv.obo"));

        return cvLookups;
    }

    public Admin getAdmin() {
        Admin admin = new Admin();

        // sample name
        admin.setSampleName(getSampleName());
        // sample description
        admin.setSampleDescription(getSampleDescription());
        // source file
//        admin.setSourceFile(getSourceFile());
        // contacts
        List<Contact> contacts = admin.getContact();
        contacts.addAll(getSampleContacts());

        return admin;
    }

    private Collection<? extends Contact> getSampleContacts() {
        Collection<Contact> contacts = null;
        List<MSContact> pcons = peptidomeReader.getSampleContacts(sampleAcc);
        if (pcons != null) {
            contacts = new ArrayList<Contact>();
            for (MSContact pcon : pcons) {
                Contact contact = new Contact();
                contact.setName(getContactName(pcon));
                contact.setInstitution(getContactInstitute(pcon));
                contact.setContactInfo(getContactEmail(pcon));
                contacts.add(contact);
            }
        }
        return contacts;
    }

    private String getContactName(MSContact contact) {
        return contact.getName() != null ? contact.getName() : (contact.getOrg() != null ? contact.getOrg() : "");
    }

    private String getContactInstitute(MSContact contact) {
        // this is a stupid method
        StringBuilder builder = new StringBuilder();
        if (contact.getOrg() != null) {
            builder.append(contact.getOrg());
            builder.append(", ");
        }

        if (contact.getDept() != null) {
            builder.append(contact.getDept());
            builder.append(", ");
        }

        if (contact.getLab() != null) {
            builder.append(contact.getLab());
            builder.append(", ");
        }

        if (contact.getAddress() != null) {
            builder.append(contact.getAddress());
            builder.append(", ");
        }

        if (contact.getCity() != null) {
            builder.append(contact.getCity());
            builder.append(", ");
        }

        if (contact.getCountry() != null) {
            builder.append(contact.getCountry());
            builder.append(", ");
        }

        if (contact.getZip() != null) {
            builder.append(contact.getZip());
            builder.append(", ");
        }

        if (contact.getPhone() != null) {
            builder.append(contact.getPhone());
            builder.append(", ");
        }

        String str = builder.toString();
        if (str.length() > 2) {
            //str = str.substring(0, str.length() - 1);
            str = str.trim().substring(0, str.trim().length() - 1);
        }
        return str;
    }

    private String getContactEmail(MSContact contact) {
        return contact.getEmail() == null ? "" : contact.getEmail();
    }

    private SampleDescription getSampleDescription() {
        SampleDescription desc = new SampleDescription();
        desc.setComment(getSampleComment());
        Param param = getSampleParams();
        desc.getCvParam().addAll(param.getCvParam());
        desc.getUserParam().addAll(param.getUserParam());
        return desc;
    }

    public String getSampleComment() {
        List<String> descs = peptidomeReader.getSampleDescription(sampleAcc);
        StringBuilder builder = new StringBuilder();
        for (String desc : descs) {
            builder.append(desc);
        }
        return builder.toString();
    }

    public Param getSampleParams() {
        Param param = new Param();
        List<CvParam> cvParams = param.getCvParam();
        List<UserParam> userParams = param.getUserParam();

        List<MSTaxon> taxons = peptidomeReader.getSampleTaxonomy(sampleAcc);
        if (taxons != null) {
            for (MSTaxon taxon : taxons) {
                cvParams.add(buildCvParam("NEWT", taxon.getId().toString(), taxon.getName(), ""));
            }
        }

        List<MSParameter> charcs = peptidomeReader.getSampleCharacteristics(sampleAcc);
        if (taxons != null) {
            for (MSParameter charc : charcs) {
                userParams.add(buildUserParam(charc.getTag(), charc.getValue()));
            }
        }

        return param;
    }

    private String getSampleName() {
        return peptidomeReader.getSampleTitle(sampleAcc);
    }

    public SourceFile getSourceFile() {
        SourceFile sourceFile = new SourceFile();
        sourceFile.setFileType("Peptidome Xml File");
        File file = peptidomeReader.getSourceFile();
        sourceFile.setNameOfFile(file.getName());
        sourceFile.setPathToFile(file.getAbsolutePath());
        return sourceFile;
    }

    public Instrument getInstrument() {
        Instrument instrument = new Instrument();
        MSSample.Instrumentation pi = peptidomeReader.getSampleInstrument(sampleAcc);
        if (pi != null) {
            // get instrument name
            String platform = pi.getPlatform();
            instrument.setInstrumentName(platform == null ? "" : platform);

            // get source

            instrument.setSource(getInstrumentSource(pi));

            // get analyzer
            instrument.setAnalyzerList(getInstrumentAnalyzer(pi));

            // get detector
            instrument.setDetector(getInstrumentDetector(pi));

            // get additional
            Param param = getInstrumentAdditionalParams(pi);
            if (param != null) {
                instrument.setAdditional(param);
            }
        }

        return instrument;
    }

    private Param getInstrumentSource(MSSample.Instrumentation instrument) {
        Param source = new Param();
        List<UserParam> sourceUserParams = source.getUserParam();
        List<String> piSources = instrument.getIonSource();
        if (piSources != null) {
            for (String piSource : piSources) {
                sourceUserParams.add(buildUserParam("Ion Source", piSource));
            }
        }
        return source;
    }

    private AnalyzerList getInstrumentAnalyzer(MSSample.Instrumentation instrument) {
        AnalyzerList analyzerList = new AnalyzerList();
        List<Param> params = analyzerList.getAnalyzer();
        List<String> analyzers = instrument.getAnalyzer();
        if (analyzers != null) {
            Param param = new Param();
            List<UserParam> userParams = param.getUserParam();
            for (String analyzer : analyzers) {
                userParams.add(buildUserParam("Analyzer", analyzer));
            }
            params.add(param);
        }
        return analyzerList;
    }

    private Param getInstrumentDetector(MSSample.Instrumentation instrument) {
        Param detector = new Param();
        List<UserParam> detectorUserParams = detector.getUserParam();
        List<String> piDetectors = instrument.getDetector();
        if (piDetectors != null) {
            for (String piDetector : piDetectors) {
                detectorUserParams.add(buildUserParam("Detector", piDetector));
            }
        }
        return detector;
    }

    private Param getInstrumentAdditionalParams(MSSample.Instrumentation instrument) {
        Param param = null;
        List<String> manus = instrument.getManufacturer();
        List<String> setups = instrument.getSetup();
        if (manus != null || setups != null) {
            param = new Param();
            List<UserParam> userParams = param.getUserParam();
            if (manus != null) {
                for (String manu : manus) {
                    userParams.add(buildUserParam("Manufacturer", manu));
                }
            }

            if (setups != null) {
                for (String setup : setups) {
                    userParams.add(buildUserParam("Setup", setup));
                }
            }
        }
        return param;
    }

    public DataProcessing getDataProcessing() {
        DataProcessing dataProcessing = new DataProcessing();

        dataProcessing.setSoftware(getSoftware());
        dataProcessing.setProcessingMethod(getProcessingMethod());

        return dataProcessing;
    }

    public Software getSoftware() {
        Software software = new Software();
        software.setVersion("unknown");
        MSSample.DataProcessing dataProcessing = peptidomeReader.getSampleDataProcessing(sampleAcc);
        if (dataProcessing != null) {
            List<String> softwareNames = dataProcessing.getSoftware();
            StringBuilder builder = new StringBuilder();
            if (softwareNames != null) {
                for (String softwareName : softwareNames) {
                    builder.append(softwareName);
                    builder.append(", ");
                }
            }
            String str = builder.toString();
            str = str.trim().substring(0, str.trim().length() - 1);
            //str = str.substring(0, str.length() - 1);
            //if (str.length() > 2) {
            //    str = str.substring(0, str.length() - 1);

            //}
            software.setName(str);

        }
        return software;
    }

    public Param getProcessingMethod() {
        Param param = null;
        MSSample.DataProcessing dataProcessing = peptidomeReader.getSampleDataProcessing(sampleAcc);
        if (dataProcessing != null) {
            List<String> ps = dataProcessing.getParameters();
            List<String> qu = dataProcessing.getQuantification();
            if (ps != null || qu != null) {
                param = new Param();
                List<UserParam> userParams = param.getUserParam();
                if (ps != null) {
                    for (String p : ps) {
                        userParams.add(buildUserParam("Parameter", p));
                    }
                }

                if (qu != null) {
                    for (String s : qu) {
                        userParams.add(buildUserParam("Quantification", s));
                    }
                }
            }
        }
        return param;
    }

    public Param getExperimentAdditional() {
        Param param = new Param();
        List<CvParam> cvParams = param.getCvParam();
        List<UserParam> userParams = param.getUserParam();

        // imported from peptidome
        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000306", "Imported from NCBI Peptidome", ""));

        // add study name
        String projectName = peptidomeReader.getStudyTitle();
        if (projectName != null) {
            cvParams.add(buildCvParam("PRIDE", "PRIDE:0000097", "Project", projectName));
        }

        // add study accession
        userParams.add(buildUserParam("Peptidome Study Accession", peptidomeReader.getStudyAccession()));
        // add study design
        String design = peptidomeReader.getStudyDesign();
        if (design != null) {
            userParams.add(buildUserParam("Study Design", peptidomeReader.getStudyDesign()));
        }

        // add study summary
        String summary = peptidomeReader.getStudySummary();
        if (summary != null) {
            userParams.add(buildUserParam("Study Summary", peptidomeReader.getStudySummary()));
        }

        return param;
    }

    private CvParam buildCvParam(String label, String accession, String name, String value) {
        CvParam cv = new CvParam();
        cv.setCvLabel(label);
        cv.setAccession(accession);
        cv.setName(name);
        if (value == null) {
            cv.setValue("");
        } else {
            cv.setValue(value);
        }
        return cv;
    }

    private UserParam buildUserParam(String name, String value) {
        UserParam up = new UserParam();
        up.setName(name);
        up.setValue(value);
        return up;
    }

    private CvLookup buildCvLookup(String label, String name, String version, String address) {
        CvLookup cvLookup = new CvLookup();
        cvLookup.setCvLabel(label);
        cvLookup.setFullName(name);
        cvLookup.setVersion(version);
        cvLookup.setAddress(address);
        return cvLookup;
    }


    public int getSpectrumCount(Collection<MgfFile> mgfs) {
        int cnt = 0;

        for (MgfFile mgfFileReader : mgfs) {
            cnt += mgfFileReader.getMs2QueryCount();
        }

        return cnt;
    }

    /**
     * Converts a ms2Query into a PRIDE Converter spectrum object.
     *
     * @param query The Ms2Query to create the spectrum on.
     * @return The generated Spectrum object.
     */
    public Spectrum createSpectrumFromMs2Query(Ms2Query query) {
        // create the spectrum
        Spectrum spectrum = new Spectrum();

        // convert the peak list to the required byte arrays
        ArrayList<Double> masses = new ArrayList<Double>();
        ArrayList<Double> intensities = new ArrayList<Double>();

        Map<Double, Double> peaks = query.getPeakList();
        for (Map.Entry<Double, Double> entry : peaks.entrySet()) {
            masses.add(entry.getKey());
            intensities.add(entry.getValue());
        }

        // create the byte arrays
        byte[] massesBytes = doubleCollectionToByteArray(masses);
        byte[] intenBytes = doubleCollectionToByteArray(intensities);

        // create the intensity array
        Data intenData = new Data();
        intenData.setEndian("little");
        intenData.setLength(intenBytes.length);
        intenData.setPrecision("64"); // doubles are 64 bit in java
        intenData.setValue(intenBytes);

        IntenArrayBinary intenArrayBin = new IntenArrayBinary();
        intenArrayBin.setData(intenData);

        // create the mass data array
        Data massData = new Data();
        massData.setEndian("little");
        massData.setLength(massesBytes.length);
        massData.setPrecision("64");
        massData.setValue(massesBytes);

        MzArrayBinary massArrayBinary = new MzArrayBinary();
        massArrayBinary.setData(massData);

        // store the mz and intensities in the spectrum
        spectrum.setIntenArrayBinary(intenArrayBin);
        spectrum.setMzArrayBinary(massArrayBinary);

        // initialize the spectrum description
        SpectrumDesc description = new SpectrumDesc();

        // create the spectrumSettings/spectrumInstrument (mzRangeStop, mzRangeStart, msLevel)
        SpectrumSettings settings = new SpectrumSettings();
        SpectrumInstrument instrument = new SpectrumInstrument();

        instrument.setMsLevel(2);

        // sort the masses to get the minimum and max
        Collections.sort(masses);
        Float rangeStart = new Float(masses.get(0));
        Float rangeStop = new Float(masses.get(masses.size() - 1));

        instrument.setMzRangeStart(rangeStart);
        instrument.setMzRangeStop(rangeStop);

        // set the spectrum settings
        settings.setSpectrumInstrument(instrument);
        description.setSpectrumSettings(settings);

        // create the precursor list
        PrecursorList precList = new PrecursorList();

        // currently, there's only one precursor supported
        precList.setCount(1);

        Precursor prec = new Precursor();
        prec.setMsLevel(1);

        Spectrum spec = new Spectrum(); // the precursor spectrum (ref)
        spec.setId(0);
        prec.setSpectrum(spec);

        Param ionSelection = new Param();

        // add the different precursor parameters if they are available
        if (query.getPeptideMass() != null)
            ionSelection.getCvParam().add(buildCvParam("MS", "MS:1000744", "selected ion m/z", query.getPeptideMass() + ""));
        if (query.getPeptideIntensity() != null)
            ionSelection.getCvParam().add(buildCvParam("MS", "MS:1000042", "peak intensity", query.getPeptideIntensity() + ""));
        if (query.getRetentionTime() != null)
            ionSelection.getCvParam().add(buildCvParam("MS", "MS:1000894", "retention time", query.getRetentionTime()));
        if (query.getChargeState() != null)
            ionSelection.getCvParam().add(buildCvParam("MS", "MS:1000041", "charge state", query.getChargeState().replaceAll("\\+", "")));
        if (query.getScan() != null)
            ionSelection.getCvParam().add(buildCvParam("MS", "MS:1000797", "peak list scans", query.getScan()));

        // save the ionselection
        prec.setIonSelection(ionSelection);

        // no activation parameters supported in MGF format
        prec.setActivation(new uk.ac.ebi.pride.jaxb.model.Param());

        // add the (only) precursor to the precursor list and save it in the description item
        precList.getPrecursor().add(prec);
        description.setPrecursorList(precList);

        spectrum.setSpectrumDesc(description);

        return spectrum;
    }

    /**
     * Converts the given collection of doubles into a
     * byte array (uses LITTLE_ENDIAN format).
     *
     * @param doubles
     * @return
     */
    private byte[] doubleCollectionToByteArray(Collection<Double> doubles) {
        // allocate the memory for the bytes to store
        ByteBuffer bytes = ByteBuffer.allocate(doubles.size() * 8);
        bytes.order(ByteOrder.LITTLE_ENDIAN); // save everything in LITTLE ENDIAN format as it's the standard for mzML

        int index = 0;

        for (Double d : doubles) {
            bytes.putDouble(index, d);
            index += 8; // increment the counter by 8
        }

        // convert the ByteBuffer to a byte[]
        byte[] byteArray = new byte[doubles.size() * 8]; // allocate the memory for the byte[] array
        bytes.get(byteArray);

        return byteArray;
    }

    public List<Identification> convertToPrideProteins(MSProtein protein, Map<String, Integer> spectrumIdMap) {
        Map<String, Identification> searchEngineToIdentificatioin = new LinkedHashMap<String, Identification>();
        List<MSPeptide> peptideRefs = protein.getPeptides().getMSPeptide();
        if (peptideRefs != null) {
            for (MSPeptide peptideRef : peptideRefs) {
                MSPeptide peptide = peptidomeReader.getSamplePeptideById(sampleAcc, peptideRef.getId().toString());
                List<MSPeptideIdent> pepIdents = peptide.getPepIdents().getMSPeptideIdent();
                peptide.setStart(peptideRef.getStart());
                peptide.setStop(peptideRef.getStop());
                for (MSPeptideIdent pepIdent : pepIdents) {
                    String searchEngine = pepIdent.getType();
                    Identification identification = searchEngineToIdentificatioin.get(searchEngine);
                    if (identification == null) {
                        identification = convertToPrideProteinWithoutPeptides(protein);
                        identification.setSearchEngine(searchEngine);
                        searchEngineToIdentificatioin.put(searchEngine, identification);
                    }
                    PeptideItem peptideItem = convertToPridePeptide(peptide, pepIdent, spectrumIdMap);
                    identification.getPeptideItem().add(peptideItem);
                }
            }
        }
        return new ArrayList<Identification>(searchEngineToIdentificatioin.values());
    }

    private PeptideItem convertToPridePeptide(MSPeptide peptide, MSPeptideIdent pepIdent, Map<String, Integer> spectrumIdMap) {
        PeptideItem peptideItem = new PeptideItem();
        peptideItem.setSequence(peptide.getSeq());
        peptideItem.setStart(peptide.getStart());
        peptideItem.setEnd(peptide.getStop());
        Integer spectrumId = spectrumIdMap.get(pepIdent.getSpectrum());
        Spectrum spectrum = null;
        if (spectrumId != null) {
            spectrum = new Spectrum();
            spectrum.setId(spectrumId.intValue());
        } else {
            System.out.println("Empty Spectrum Reference: " + pepIdent.getSpectrum());
            //System.exit(0);
        }
        peptideItem.setSpectrum(spectrum);
        peptideItem.getModificationItem().addAll(convertPeptidePTM(peptide.getSeq(), pepIdent));
        Param param = new Param();
        List<UserParam> userParams = param.getUserParam();
        Double expMass = pepIdent.getExpmass();
        if (expMass != null) {
            userParams.add(buildUserParam("Experimental Mass", expMass.toString()));
        }
        Double theoMass = pepIdent.getTheomass();
        if (theoMass != null) {
            userParams.add(buildUserParam("Theoretical Mass", theoMass.toString()));
        }
        Double deltaMass = pepIdent.getDeltamass();
        if (deltaMass != null) {
            userParams.add(buildUserParam("Delta Mass", deltaMass.toString()));
        }

        boolean hasAdditional = false;
        List<CvParam> cvParams = param.getCvParam();
        BigInteger charge = pepIdent.getCharge();
        if (charge != null) {
            hasAdditional = true;
            cvParams.add(buildCvParam("MS", "MS:1000041", "charge state", charge.toString()));
        }


        String searchEngineType = pepIdent.getType();
        MSPeptideIdent.Scores scores = pepIdent.getScores();
        if (scores != null) {
            List<MSScore> msScores = scores.getMSScore();
            hasAdditional = (msScores.size() > 0);
            for (MSScore msScore : msScores) {
                //System.out.println(msScore.getType() + "\n");

                if (searchEngineType.toLowerCase().equals("mascot")) {

                    //System.out.println("HIT" + "\n");

                    if (msScore.getType().equals("expect")) {


                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000212", "Mascot expect value", msScore.getValue() + ""));

                    } else {

                        userParams.add(buildUserParam(msScore.getType(), msScore.getValue() + ""));
                    }

                    //} else if (searchEngineType.toLowerCase().equals("")) {

                } else if (searchEngineType.toLowerCase().equals("sequest")) {

                    if (msScore.getType().equals("xcorr")) {

                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000053", "Sequest score", msScore.getValue() + ""));

                    } else if (msScore.getType().equals("deltacn")) {

                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000012", "Delta Cn", msScore.getValue() + ""));

                    } else if (msScore.getType().equals("spscore")) {

                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000054", "Sp", msScore.getValue() + ""));

                    } else {

                        userParams.add(buildUserParam(msScore.getType(), msScore.getValue() + ""));
                    }

                } else if (searchEngineType.toLowerCase().equals("x! tandem")) {


                    if (msScore.getType().equals("hyperscore")) {

                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000176", "X!Tandem Hyperscore", msScore.getValue() + ""));

                    }

                    if (msScore.getType().equals("expect")) {

                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000183", "expect", msScore.getValue() + ""));

                    } else {

                        userParams.add(buildUserParam(msScore.getType(), msScore.getValue() + ""));
                    }


                } else if (searchEngineType.toLowerCase().equals("omssa")) {

                    if (msScore.getType().equals("evalue")) {

                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000185", "OMSSA E-value", msScore.getValue() + ""));

                    } else if (msScore.getType().equals("pvalue")) {

                        cvParams.add(buildCvParam("PRIDE", "PRIDE:0000186", "OMSSA P-value", msScore.getValue() + ""));

                    } else {

                        userParams.add(buildUserParam(msScore.getType(), msScore.getValue() + ""));
                    }

                } else {
                    userParams.add(buildUserParam(msScore.getType(), msScore.getValue() + ""));

                }
            }
        }
        //  else if{

        //  }
        if (hasAdditional) {
            peptideItem.setAdditional(param);
        }
        return peptideItem;
    }

    private List<ModificationItem> convertPeptidePTM(String sequence, MSPeptideIdent pepIdent) {
        List<ModificationItem> modItems = new ArrayList<ModificationItem>();
        // variable
        MSPeptideIdent.Mods mods = pepIdent.getMods();
        if (mods != null) {
            List<MSPTM> msptms = mods.getMSPTM();
            for (MSPTM msptm : msptms) {
                String unimodId = msptm.getUnimodId().toString();
                int location = msptm.getPosition().intValue();
                ModificationItem modItem = copyOfPTM(unimodPTMs.get(unimodId));
                modItem.setModLocation(new BigInteger(location + ""));
                modItems.add(modItem);
            }
        }

        // fixed
        MSFraction fraction = peptidomeReader.getSampleFractionById(sampleAcc, pepIdent.getFraction());
        MSFraction.FixedMods fixedMods = fraction.getFixedMods();
        if (fixedMods != null) {
            List<MSPTM> fixedMSPtms = fixedMods.getMSPTM();
            for (MSPTM fixedMSPtm : fixedMSPtms) {
                String unimodId = fixedMSPtm.getUnimodId().toString();
                String residue = fixedMSPtm.getResidue();
                char[] chars = sequence.toCharArray();
                for (int i = 0; i < chars.length; i++) {
                    if (residue.charAt(0) == chars[i]) {
                        ModificationItem modItem = copyOfPTM(unimodPTMs.get(unimodId));
                        modItem.setModLocation(new BigInteger((i+1) + ""));
                        // label fixed
                        Param param = modItem.getAdditional();
                        List<CvParam> cvParams = param.getCvParam();
                        CvParam fixedModParam = new CvParam();
                        fixedModParam.setCvLabel("PRIDE");
                        fixedModParam.setAccession("PRIDE:0000282");
                        fixedModParam.setName("Fixed modification");
                        fixedModParam.setValue("");
                        cvParams.add(fixedModParam);

                        modItems.add(modItem);
                    }
                }
            }
        }

        return modItems;
    }

    private ModificationItem copyOfPTM(ModificationItem modificationItem) {
        ModificationItem item = new ModificationItem();
        item.setModAccession(modificationItem.getModAccession());
        item.setModDatabase(modificationItem.getModDatabase());
        item.setModDatabaseVersion(modificationItem.getModDatabaseVersion());
        item.getModAvgDelta().addAll(modificationItem.getModAvgDelta());
        item.getModMonoDelta().addAll(modificationItem.getModMonoDelta());
        Param param = new Param();
        Param originalParam = modificationItem.getAdditional();
        param.getCvParam().addAll(originalParam.getCvParam());
        param.getUserParam().addAll(originalParam.getUserParam());
        item.setAdditional(param);
        return item;
    }

    private Identification convertToPrideProteinWithoutPeptides(MSProtein protein) {
        Identification identification = new GelFreeIdentification();
        String accession = protein.getAcc();
        String proteinName = protein.getName();
        if (accession == null || "".equals(accession)) {
            if (proteinName != null) {
                accession = proteinName;
            }
        }

        identification.setAccession(accession);
        identification.setDatabase("unknown");
        identification.setDatabaseVersion("unknown");
        identification.setSpectrum(null);
        identification.setScore(null);
        identification.setThreshold(null);
        BigInteger coverage = protein.getCoverage();
        if (coverage != null) {
            identification.setSequenceCoverage(coverage.doubleValue());
        }
        Param param = new Param();
        identification.setAdditional(param);
        List<UserParam> userParams = param.getUserParam();
        // GI number
        BigInteger gi = protein.getGi();
        if (gi != null) {
            userParams.add(buildUserParam("NCBI GI", gi.toString()));
        }
        // protein mass
        Double mass = protein.getMass();
        if (mass != null && mass > 0) {
            userParams.add(buildUserParam("Protein Mass", mass.toString()));
        }

        // protein define line
        String defLine = protein.getDefline();
        if (defLine != null) {
            userParams.add(buildUserParam("Define Line", defLine));
        }
        MSProtein.Gene gene = protein.getGene();
        if (gene != null) {
            // gene id
            userParams.add(buildUserParam("Gene ID", gene.getMSGeneRef().getId().toString()));
            // gene symbol
            userParams.add(buildUserParam("Gene Symbol", gene.getMSGeneRef().getSymbol()));
        }


        List<CvParam> cvParams = param.getCvParam();

        //protein name
        if (proteinName != null) {
            cvParams.add(buildCvParam("MS", "MS:1000886", "protein name", proteinName));
        }
        //taxonomy
        MSProtein.Taxon taxon = protein.getTaxon();
        if (taxon != null) {
            String id = taxon.getMSTaxon().getId().toString();
            if (id != null && !"".equals(id.trim()) && !"0".equals(id.trim())) {
                String name = taxon.getMSTaxon().getName();
                cvParams.add(buildCvParam("NEWT", id, name, id));
            }
        }
        // protein sequence length
        BigInteger length = protein.getLength();
        if (length != null && length.intValue() > 0) {
            cvParams.add(buildCvParam("PRIDE", "PRIDE:0000172", "Search database protein sequence length", length.toString()));
        }

        return identification;
    }
}
